home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dirut / ddir0789.zip / DDIR.ASM next >
Assembly Source File  |  1989-05-24  |  13KB  |  447 lines

  1. ;╔════════════════════════════════════════════════════════════╗
  2. ;║    DDIR.ASM -- Double Column Sorted DIR Command          ║
  3. ;║    ────────                          ║
  4. ;║            (C) Copyright Charles Petzold, 1985   ║
  5. ;║    DOS 4.x version (C) Copyright Roger M. Wilcox, 1989   ║
  6. ;║            COM file format                  ║
  7. ;╚════════════════════════════════════════════════════════════╝
  8.  
  9. CSEG        Segment
  10.  
  11.         Assume    CS:CSEG, DS:CSEG
  12.  
  13.         Org    002Ch            ; Offset of Environment
  14. Environment    Label    Byte
  15.  
  16.         Org    007Bh            ; Parameter for COMMAND.COM
  17. NewParameter    Label    Byte
  18.  
  19.         Org    0080h            ; Parameter passed to program
  20. OldParameter    Label    Byte    
  21.  
  22.         Org    0100h            ; Entry point
  23. Entry:        Jmp    Begin
  24.  
  25. ;    All Data
  26. ;    --------
  27.  
  28.         db    '(C) Copyright Charles Petzold, 1985'
  29.  
  30. DosVersMsg    db    "Needs DOS 2.00 +$"    ; Error messages
  31. MemAllocMsg    db    "Memory Problem$"
  32. CommandMsg    db    "COMMAND Problem$"
  33.  
  34. Comspec        db    "COMSPEC="        ; Search string in environment
  35. CommandAsciiz    dd    ?            ; Eventual pointer to COMMAND
  36.  
  37. ParamBlock    dw    ?            ; Parameter Block for EXEC
  38.         dw    NewParameter,?        ; First ? must be replaced
  39.         dw    5Ch,?            ;    with Environment segment;
  40.         dw    6Ch,?            ;    others with this segment
  41.  
  42. OldInterrupt21    dd    ?            ; For vector address storage
  43.  
  44. BufferPtr    dw    Offset FileBuffer    ; For storing files listing
  45. CharCounter    dw    0            ; Keeps track of characters
  46. NowDoingFile    db    0            ; Flagged for file printed
  47. WithinFileList    db    0            ; Flagged for file list
  48. FileCounter    dw    0            ; Keeps track of files
  49. LineCounter    db    0            ; For pausing at screen end
  50.  
  51. PauseMessage    db    6 dup (205)," Press any key to continue "
  52.         db    6 dup (205),181
  53. PauseMsgEnd    Label    Byte
  54.  
  55. ;    Check DOS Version
  56. ;    -----------------
  57.  
  58. Begin:        Mov    AH,30h            ; DOS Version function call
  59.         Int    21h            ; Call DOS
  60.         Cmp    AL,2            ; Check if version 2
  61.         Jae    DosVersOK        ; If equal or over, all OK
  62.  
  63.         Mov    DX,Offset DosVersMsg    ; Wrong DOS version message
  64. ErrorExit:    Mov    AH,9            ; Set up for string write
  65.         Int    21h            ; Call DOS for message
  66.  
  67.         Int    20h            ; Dishonorable discharge
  68.  
  69. ;    Adjust stack and un-allocate rest of memory
  70. ;    -------------------------------------------
  71.  
  72. DosVersOK:    Mov    DI,Offset FileBuffer    ; Place to save files
  73.         Mov    CX,528 * 39        ; Allow room for 528 files
  74.         Mov    AL,' '            ; Will clear with blanks
  75.         Cld                ; Forward direction
  76.         Rep    Stosb            ; Clear the area
  77.  
  78.         Mov     BX,(Offset FileBuffer) + (528 * 39) + 100h
  79.                          ; New end of program
  80.         Mov    SP,BX            ; Set the stack pointer
  81.         Add    BX,15            ; Add 15 for rounding
  82.         Mov    CL,4            ; Number of shifts
  83.         Shr    BX,CL            ; Convert AX to segment
  84.  
  85.         Mov    AH,4Ah            ; DOS call to shrink down
  86.         Int    21h            ;    allocated memory
  87.  
  88.         Mov    DX,Offset MemAllocMsg    ; Possible error message
  89.         Jc    ErrorExit        ; Only print it if Carry set
  90.  
  91. ;    Search for Comspec in Environment
  92. ;    ---------------------------------
  93.  
  94.         Mov    ES,[Environment]    ; Environment Segment
  95.         Sub    DI,DI            ; Start search at beginning
  96.         Cld                ; String increment to forward
  97.  
  98. TryThis:    Cmp    Byte Ptr ES:[DI],0    ; See if end of environment
  99.         Jz    NoFindComSpec        ; If so, we have failed
  100.  
  101.         Push    DI            ; Save environment pointer
  102.         Mov    SI,Offset ComSpec    ; String to search for
  103.         Mov    CX,8            ; Characters in search string
  104.         Repz    Cmpsb            ; Check if strings are same
  105.         Pop    DI            ; Get back the pointer
  106.  
  107.         Jz    FoundComspec        ; Found string only zero flag
  108.  
  109.         Sub    AL,AL            ; Zero out AL
  110.         Mov    CX,8000h        ; Set for big search
  111.         Repnz    Scasb            ; Find the next zero in string
  112.         Jmp    TryThis            ; And do the search from there
  113.  
  114. NoFindComSpec:    Mov    DX,Offset CommandMsg    ; Message for COMSPEC error
  115.         Jmp    ErrorExit        ; Print it and exit
  116.  
  117. FoundComspec:    Add    DI,8            ; So points after 'COMSPEC='
  118.         Mov    Word Ptr [CommandASCIIZ],DI    ; Save the address of
  119.         Mov    Word Ptr [CommandASCIIZ + 2],ES    ;    COMMAND ASCIIZ
  120.  
  121. ;     Set up parameter block for EXEC call
  122. ;    ------------------------------------
  123.  
  124.         Mov    [ParamBlock],ES        ; Segment of Environment string
  125.         Mov    [ParamBlock + 4],CS    ; Segment of this program
  126.         Mov    [ParamBlock + 8],CS    ;    so points to FCB's
  127.         Mov    [ParamBlock + 12],CS    ;    and NewParameter
  128.  
  129. ;    Save and set Interrupt 21h vector address
  130. ;    -----------------------------------------
  131.  
  132.         Mov    AX,3521h        ; DOS call to get Interrupt 21
  133.         Int    21h            ;    vector address
  134.         Mov    Word Ptr [OldInterrupt21],BX        ; Save offset
  135.         Mov    Word Ptr [OldInterrupt21 + 2],ES    ; And segment
  136.  
  137.         Mov    DX,Offset NewInterrupt21; Address of new Interrupt 21
  138.         Mov    AX,2521h        ; Do DOS call to
  139.         Int    21h            ;    set the new address
  140.  
  141. ;    Fix up new parameter for "/C DIR" String
  142. ;    ----------------------------------------
  143.  
  144.         Mov    AL,[OldParameter]    ; Number of parameter chars
  145.         Add    AL,5            ; We'll be adding five more
  146.         Mov    [NewParameter],AL    ; Save it
  147.         Mov    Word Ptr [NewParameter + 1],'C/'    ; i.e. "/C"
  148.         Mov    Word Ptr [NewParameter + 3],'ID'    ; Then "DI"
  149.         Mov    Byte Ptr [NewParameter + 5],'R'        ; And "R"
  150.  
  151. ;     Load COMMAND.COM
  152. ;     ----------------
  153.  
  154.         Push    CS            ; Push this segment so we can
  155.         Pop    ES            ;    set ES to it
  156.         Mov    BX,Offset ParamBlock    ; ES:BX = address of block
  157.         Lds    DX,[CommandAsciiz]    ; DS:DX = address of ASCIIZ
  158.         Mov    AX,4B00h        ; EXEC call 4Bh, type 0
  159.         Int    21h            ; Load command processor
  160.  
  161. ;     Return from COMMAND.COM
  162. ;    -----------------------
  163.  
  164.         Mov    AX,CS        ; Get this segment in AX
  165.         Mov    DS,AX        ; Set DS to it
  166.         Mov    SS,AX        ; And SS for stack segment
  167.         Mov    SP,(Offset FileBuffer) + (528 * 39) + 100h
  168.                     ; Set Stack again
  169.  
  170.         PushF            ; Save Carry for error check
  171.         Push    DS        ; Save DS during next call
  172.  
  173.         Mov    DX,Word Ptr [OldInterrupt21]    ; Old Int 21 offset
  174.         Mov    DS,Word Ptr [OldInterrupt21 + 2]; and segment
  175.         Mov    AX,2521h        ; Call DOS to set vector
  176.         Int    21h            ;    address to original
  177.  
  178.         Pop    DS            ; Restore DS to this segment
  179.         PopF                ; Get back Carry flage
  180.  
  181.         Jnc    NormalEnd        ; Continue if no error
  182.  
  183.         Mov    DX,Offset CommandMsg    ; Otherwise we'll print error
  184.         Jmp    ErrorExit        ;    message and exit
  185.  
  186. NormalEnd:    Int    20h            ; Terminate program
  187.  
  188. ;    New Interrupt 21h
  189. ;    -----------------
  190.  
  191. NewInterrupt21    Proc    Far
  192.  
  193.         Sti                ; Allow further interrupts
  194.         Cmp    AH,40h            ; Check if file / device write
  195.         Je    CheckHandle        ; If so, continue checks
  196.  
  197. SkipIntercept:    Jmp    CS:[OldInterrupt21]    ; Just jump to old interrupt
  198.  
  199. CheckHandle:    Cmp    BX,1            ; Check if standard output
  200.         Jne    SkipIntercept        ; Not interested if not
  201.  
  202.         PushF                ; Push all registers that
  203.         Push    AX            ;    we'll be messing with
  204.         Push    CX
  205.         Push    SI
  206.         Push    DI
  207.         Push    ES
  208.  
  209.         Push    CS            ; Push the code segment
  210.         Pop    ES            ; So we can set ES to it
  211.         Cld                ; Forward for string transfers
  212.         Mov    SI,DX            ; Now DS:SI = text source
  213.         Mov    DI,CS:[BufferPtr]    ; And ES:DI = text destination
  214.  
  215.         Cmp    CX,2            ; See if two chars to write
  216.         Jne    RegularChars        ; If not, can't be CR/LF
  217.  
  218.         Cmp    Word Ptr DS:[SI],0A0Dh    ; See if CR/LF being written
  219.         Jne    RegularChars        ; Skip rest if not CR/LF
  220.  
  221.         Mov    CX,CS:[CharCounter]    ; Get characters in line
  222.         Mov    CS:[CharCounter],0    ; Start at new line
  223.         Cmp    CS:[NowDoingFile],1    ; See if CR/LF terminates file
  224.         Jnz    Kludge            ; If not, just write to screen
  225.  
  226.         Mov    AX,39            ; Max characters per line
  227.         Sub    AX,CX            ; Subtract those passed
  228.         Add    CS:[BufferPtr],AX    ; Kick up pointer by that
  229.         Mov    CS:[NowDoingFile],0    ; Finished with file
  230.         Jmp    PopAndReturn        ; So just return to COMMAND
  231. Kludge:        JMP    AllowTransfer
  232.  
  233. RegularChars:    Add    CS:[CharCounter],CX    ; Kick up counter by number
  234.         Cmp    CS:[CharCounter],CX    ; See if beginning of line
  235.         Jne    NotLineBegin        ; If not, must be in middle
  236.  
  237.         Cmp    Byte Ptr DS:[SI],' '    ; See if first char is blank
  238.         Je    Cont            ; If so, it ain't a file line
  239.         CMP    WORD PTR DS:[SI],'oV'    ; Vo(lume ...)
  240.         JE    Cont
  241.         CMP    WORD PTR DS:[SI],'iD'    ; Di(rectory of ...)
  242.         JNE    ItsAFile
  243.  
  244. Cont:        Cmp    CS:[WithinFileList],1    ; See if doing file listing
  245.         Jne    AllowTransfer        ; If not, just print stuff
  246.  
  247.         Call    SortAndList        ; Files done -- sort and list
  248.         Mov    CS:[WithinFileList],0    ; Not doing files now
  249.         Jmp    Short AllowTransfer    ; So just print the stuff
  250.  
  251. ItsAFile:    Cmp    CS:[FileCounter],528    ; See if 11 buffer filled up
  252.         Jb    NotTooManyFiles        ; If not just continue
  253.  
  254.         Push    CX            ; Otherwise, save this register
  255.         Call    SortAndList        ; Print all up to now
  256.         Mov    CS:[FileCounter],0    ; Reset the counter
  257.         Mov    DI